package botlab;

import botlab.command.BaseCommand;
import botlab.gui.levelchooser.actionlistener.SelectActionListener;
import botlab.level.Level;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.ui.Picture;
import java.util.logging.Logger;

/**
 * Game app class
 *
 * @author Quentin
 */
public class Game extends SimpleApplication
{

    protected static Game app;
    protected static BitmapText text;
    protected Level currentLevel;
    protected BulletAppState bulletAppState;
    protected boolean pause;
    protected Picture pic;

    public static Game getApp()
    {
        return app;
    }

    public static void setApp(Game a)
    {
        app = a;
    }

    @Override
    public void simpleInitApp()
    {
        super.setDisplayFps(false);
        super.setDisplayStatView(false);
        String userHome = System.getProperty("user.home");
        assetManager.registerLocator(userHome, FileLocator.class);

        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.setEnabled(false);
        bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0, 0, 0));

        this.getFlyByCamera().setMoveSpeed(30);


        /**
         * Write text on the screen (HUD)
         */
        this.getGuiNode().detachAllChildren();
//        BitmapFont guiFont = this.getAssetManager().loadFont(
//                "Interface/Fonts/Default.fnt");
        BitmapText helloText = new BitmapText(guiFont, false);
        helloText.setSize(guiFont.getCharSet().getRenderedSize());
        helloText.setText("");
        helloText.setLocalTranslation(10, helloText.getLineHeight(), 0);
        this.getGuiNode().attachChild(helloText);
        text = helloText;

        pic = new Picture("HUD Pic");

        initKeys();
    }

    private void initKeys()
    {
        // You can map one or several inputs to one named action
        inputManager.addMapping(
                "pause",
                new KeyTrigger(KeyInput.KEY_P),
                new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
        // Add the names to the action listener.
        inputManager.addListener(actionListener, new String[]
                {
                    "pause"
                });
    }
    private ActionListener actionListener = new ActionListener()
    {
        public void onAction(String name, boolean keyPressed, float tpf)
        {
            if (name.equals("pause") && !keyPressed)
            {
                if (pause)
                {
                    unpause();
                } else
                {
                    pause();
                }


            }
        }
    };

    public void pause()
    {
        currentLevel.dettach();
        bulletAppState.setEnabled(false);
        pause = !pause;
    }

    public void unpause()
    {
        text.setText("");
        if (!currentLevel.isAttached())
        {
            currentLevel.attach();
        }
        bulletAppState.getPhysicsSpace().clearForces();
        bulletAppState.setEnabled(true);
        pause = !pause;
    }

    public void win()
    {
        int w = GameManager.getInstance().getCanvas().getWidth();
        int h = GameManager.getInstance().getCanvas().getHeight();
        pic.setImage(assetManager, "Textures/pictures/win.png", true);
        pic.setWidth(w);
        pic.setHeight(h);
        pic.setPosition(0, 0);
        guiNode.attachChild(pic);
        pause();
    }

    public void loose()
    {
        int w = GameManager.getInstance().getCanvas().getWidth();
        int h = GameManager.getInstance().getCanvas().getHeight();
        pic.setImage(assetManager, "Textures/pictures/game_over.png", true);
        pic.setWidth(w);
        pic.setHeight(h);
        pic.setPosition(0, 0);
        guiNode.attachChild(pic);
        pause();
    }

    public void cleanup()
    {
        if (currentLevel != null)
        {
            // Remove rigidBodyControls and Joints recursively
            bulletAppState.getPhysicsSpace().removeAll(
                    currentLevel.getLevelNode());

            currentLevel.dettach();
            currentLevel.cleanup();
        }
        UserLib.cleanupForces();
        getText().setText("");
        guiNode.detachChild(pic);
    }

    public void loadLevel(Level l, java.awt.event.ActionListener callBack)
    {
        this.currentLevel = l;
        currentLevel.load();
        /*
         * attaching level for the first time is a bit time-consuming,
         * so we have to do it when loading and not when starting.
         */
        currentLevel.attach();


        if (callBack != null)
        {
            ((SelectActionListener) callBack).levelLoaded();
        }
    }

    public void startLevel(BaseCommand userCommand)
    {
        UserLib.init(this);
        /*
         * If the level isn't loaded yet, it means that it's not the fisrt time
         * it's started. Thus the loading will be quick. (the assetManager keeps
         * loaded meshes in memory).
         */
        if (getCurrentLevel().isLoaded())
            cleanup();
        loadLevel(getCurrentLevel(), null);

        currentLevel.start(userCommand);
        bulletAppState.setEnabled(true);

    }

    public void stopLevel()
    {
        cleanup();
        bulletAppState.setEnabled(false);
    }

    @Override
    public void simpleUpdate(float tpf)
    {
    }

    @Override
    public void simpleRender(RenderManager rm)
    {
    }

    public static BitmapText getText()
    {
        return text;
    }

    public Level getCurrentLevel()
    {
        return currentLevel;
    }

    public boolean isPaused()
    {
        return pause;
    }

    public Picture getPic()
    {
        return pic;
    }
    
    
}
